/**
 * Copyright 2018 人人开源 http://www.renren.io
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.nbjtjc.safe.job.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.nbjtjc.safe.bean.Constant;
import com.nbjtjc.safe.job.mapper.ScheduleJobMapper;
import com.nbjtjc.safe.job.model.ScheduleJobEntity;
import com.nbjtjc.safe.job.utils.ScheduleUtils;
import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;

@Service("scheduleJobService")
public class ScheduleJobService {
    @Autowired
    private Scheduler scheduler;

    @Autowired
    private ScheduleJobMapper scheduleJobMapper;

    /**
     * 项目启动时，初始化定时器
     */
    @PostConstruct
    public void init() {
        List<ScheduleJobEntity> scheduleJobList = scheduleJobMapper.selectAll();
        for (ScheduleJobEntity scheduleJob : scheduleJobList) {
            // 简单表达式的trigger（触发器）
            if (scheduleJob.getJobTriggerType().equals(Constant.ScheduleJobTriggerType.SIMPLETRIGGER.getValue())) {
                SimpleTrigger simpleTrigger = ScheduleUtils
                        .getSimpleTrigger(scheduler, scheduleJob.getJobId());
                if(ObjectUtil.isNull(simpleTrigger)&&scheduleJob.getJobTime().after(new Date())){
                    ScheduleUtils.createScheduleJob(scheduler,scheduleJob,scheduleJob.getJobTime()
                    ,simpleTrigger.getRepeatCount(),simpleTrigger.getRepeatInterval());
                }else if (ObjectUtil.isNotNull(simpleTrigger)){
//                    ScheduleUtils.updateSimpleScheduleJob(scheduler,scheduleJob);
                    ScheduleUtils.updateSimpleScheduleJob(scheduler,scheduleJob
                    ,simpleTrigger.getStartTime(),simpleTrigger.getRepeatCount()
                            ,simpleTrigger.getRepeatInterval()/1000);
                }
            }
            //表达式的触发器
            if (scheduleJob.getJobTriggerType()
                    .equals(Constant.ScheduleJobTriggerType.CRONTRIGGER.getValue())) {
                CronTrigger cronTrigger = ScheduleUtils.getCronTrigger(scheduler, scheduleJob.getJobId());
                //如果不存在，则创建
                if (cronTrigger == null) {
                    ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
                } else {
                    ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);
                }
            }
        }
    }

    public PageInfo find(ScheduleJobEntity scheduleJobEntity) {
        PageHelper.startPage(scheduleJobEntity.getPageCurrent(), scheduleJobEntity.getPageSize());
        List<ScheduleJobEntity> scheduleJobEntities = scheduleJobMapper.search(scheduleJobEntity);
        return new PageInfo(scheduleJobEntities);
    }


    @Transactional(rollbackFor = Exception.class)
    public void save(ScheduleJobEntity scheduleJob) {
        scheduleJob.setCreateTime(new Date());
        scheduleJob.setStatus(Constant.ScheduleStatus.NORMAL.getValue());
        scheduleJobMapper.insertSelective(scheduleJob);
        ScheduleUtils.createScheduleJob(scheduler, scheduleJob);
    }

    @Transactional(rollbackFor = Exception.class)
    public void update(ScheduleJobEntity scheduleJob) {
        ScheduleUtils.updateScheduleJob(scheduler, scheduleJob);

        scheduleJobMapper.updateByPrimaryKeySelective(scheduleJob);
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteBatch(Long[] jobIds) {
        for (Long jobId : jobIds) {
            ScheduleUtils.deleteScheduleJob(scheduler, jobId);
            scheduleJobMapper.deleteByPrimaryKey(jobId);
        }

        //删除数据
        //TODO 批量删除
//    	(Arrays.asList(jobIds));

    }

    public int updateBatch(Long[] jobIds, int status) {
        Map<String, Object> map = new HashMap<>();
        map.put("list", jobIds);
        map.put("status", status);
//    	return baseMapper.updateBatch(map);
        //TODO 批量更新
        return scheduleJobMapper.updateStatusBatch(CollectionUtil.newArrayList(jobIds),status);
    }

    @Transactional(rollbackFor = Exception.class)
    public void run(Long[] jobIds) {
        for (Long jobId : jobIds) {
            ScheduleUtils.run(scheduler, scheduleJobMapper.selectByPrimaryKey(jobId));
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void pause(Long[] jobIds) {
        for (Long jobId : jobIds) {
            ScheduleUtils.pauseJob(scheduler, jobId);
        }

        updateBatch(jobIds, Constant.ScheduleStatus.PAUSE.getValue());
    }

    @Transactional(rollbackFor = Exception.class)
    public void resume(Long[] jobIds) {
        for (Long jobId : jobIds) {
            ScheduleUtils.resumeJob(scheduler, jobId);
        }

        updateBatch(jobIds, Constant.ScheduleStatus.NORMAL.getValue());
    }

}
